﻿using Microsoft.Maps.MapControl.WPF;
using Microsoft.Research.DynamicDataDisplay.Charts.Navigation;
using Microsoft.Research.DynamicDataDisplay.DataSources;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using TrailMapManager.Common;
using TrailMapManager.Common.Track;

namespace TrailMapManager.Modules.Track.Logic
{
    public class TrackMainViewLogic : BaseViewLogic
    {
        #region properties
        public override bool IsBusy
        {
            get
            {
                return base.IsBusy | TrailTrackMan.IsBusy;
            }
            set
            {
                base.IsBusy = value;
            }
        }


        private Location _mapCenter;
        public Location MapCenter
        {
            get { return _mapCenter; }
            set { _mapCenter = value; NotifyPropertyChanged("MapCenter"); }
        }

        public TrailTrackManager TrailTrackMan
        {
            get
            {
                return TrailTrackManager.Instance;
            }
        }

        public List<TrailTrackPoint> ChartData;

        private TrailTrack _selectedTrack;
        public TrailTrack SelectedTrack
        {
            get { return _selectedTrack; }
            set
            {
                _selectedTrack = value;
                NotifyPropertyChanged("SelectedTrack");
                NotifyPropertyChanged("TrackPoints");
                MoveCenterLittleBit();
                UpdateDiagramData();

            }
        }

        private Location _markerLocation;
        public Location MarkerLocation
        {
            get { return _markerLocation; }
            set { _markerLocation = value; NotifyPropertyChanged("MarkerLocation"); }
        }

        private string _markerSpeedText;
        public string MarkerSpeedText
        {
            get { return _markerSpeedText; }
            set { _markerSpeedText = value; NotifyPropertyChanged("MarkerSpeedText"); }
        }

        private string _markerAltitudeText;
        public string MarkerAltitudeText
        {
            get { return _markerAltitudeText; }
            set { _markerAltitudeText = value; NotifyPropertyChanged("MarkerAltitudeText"); }
        }

        private DateTime _cursorPosition;
        public DateTime CursorPosition
        {
            get { return _cursorPosition; }
            set
            {
                _cursorPosition = value;
                NotifyPropertyChanged("CursorPosition");
                var currentChartData = (from ttp in ChartData
                                        where ttp.TimeStamp.ToLongTimeString().Equals(value.ToLongTimeString())
                                        select ttp).FirstOrDefault();
                if (currentChartData != null)
                {
                    MarkerLocation = currentChartData.Position;
                    MapCenter = currentChartData.Position;
                    MarkerSpeedText = Math.Round(currentChartData.Speed, 1).ToString() + "km/h";
                    MarkerAltitudeText = Math.Round(currentChartData.Altitude, 0).ToString() + "m";
                }
            }
        }
        #endregion

        #region commands
        private RelayCommand _deleteTrackCommand;
        public RelayCommand DeleteTrackCommand
        {
            get
            {
                if (_deleteTrackCommand == null)
                {
                    _deleteTrackCommand = new RelayCommand(
                        () =>
                        {
                            this.DeleteTrack(SelectedTrack);
                        },
                        () =>
                        {
                            return SelectedTrack != null;
                        });
                }
                return _deleteTrackCommand;
            }
        }

        private RelayCommand _exportCommand;
        public RelayCommand ExportCommand
        {
            get
            {
                if (_exportCommand == null)
                {
                    _exportCommand = new RelayCommand(
                        () =>
                        {
                            this.Export(SelectedTrack);
                        },
                        () =>
                        {
                            return SelectedTrack != null;
                        });
                }
                return _exportCommand;
            }
        }

        #endregion

        public TrackMainViewLogic()
        {
            ChartData = new List<TrailTrackPoint>();
            MapCenter = new Location();
            MarkerLocation = new Location();
        }

        #region func
        public LocationCollection TrackPoints
        {
            get
            {
                var locations = new LocationCollection();
                if (SelectedTrack != null)
                {
                    foreach (var point in SelectedTrack.Points)
                    {
                        locations.Add(point.Position);
                    }
                }
                return locations;
            }
        }

        private void Export(TrailTrack SelectedTrack)
        {
            Microsoft.Win32.SaveFileDialog saveFD = new Microsoft.Win32.SaveFileDialog();
            saveFD.AddExtension = true;
            saveFD.CheckFileExists = false;
            saveFD.DefaultExt = "gpx";
            saveFD.Filter = "GPS eXchange Format | *.gpx";
            if ((bool)saveFD.ShowDialog())
            {
                string path = saveFD.FileName;
                TrailTrackManager.Instance.GenerateGPX(SelectedTrack.Id, path);
            }
        }


        private void UpdateDiagramData()
        {
            ChartData.Clear();
            if (SelectedTrack == null)
            {
                return;
            }
            ThreadPool.QueueUserWorkItem(
                a =>
                {
                    List<TrailTrackPoint> points = new List<TrailTrackPoint>();
                    foreach (var point in SelectedTrack.Points)
                    {
                        if (double.IsNaN(point.Speed))
                        {
                            point.Speed = 0;
                        }
                        //Speed in m/s convert to km/h
                        points.Add(new TrailTrackPoint() { Altitude = point.Altitude, Position = point.Position, Speed = point.Speed * 3.6, TimeStamp = point.TimeStamp });
                    }
                    Application.Current.Dispatcher.BeginInvoke(new Action(
                        () =>
                        {
                            ChartData.AddRange(points);
                            NotifyUpdate();
                        }));

                });
        }

        private void DeleteTrack(TrailTrack track)
        {
            TrailTrackManager.Instance.DeleteTrack(track.Id);
        }

        public delegate void UpdateDelegate();
        public event UpdateDelegate Update;
        private void NotifyUpdate()
        {
            if (Update != null)
            {
                Update();
            }
        }

        private void MoveCenterLittleBit()
        {
            new Task(
                () =>
                {
                    var oldCenter = MapCenter;
                    var newCenter = new Location(MapCenter.Latitude, MapCenter.Longitude + 0.00000000001);
                    InvokeOnMainThread(
                        () =>
                        {
                            MapCenter = newCenter;
                        });
                    Thread.Sleep(10);
                    InvokeOnMainThread(
                        () =>
                        {
                            MapCenter = oldCenter;
                        });
                }).Start();
        }
        #endregion
    }


}
